# coding: utf-8
import uuid

from django.db import models, IntegrityError
from lib.common import BasicManager
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

from project.settings import DOMAIN_URL
from project.settings_common import EVALUATION_0_Link
from services.datamodel.student.models import Student
import json
import os
from apps.student.share import app_logger
import collections
from django.db.models import Q
import xlwt
from io import BytesIO
from django.http import HttpResponse, JsonResponse


class ModelManagerEvaluation(BasicManager):
    # 获取列表
    def get_list(self, page, is_show=None):
        result = self.values().order_by("-created_at")
        if is_show:
            result = result.filter(is_show=is_show)
        if not page:
            return {'retcode': 0, 'retlist': list(result)}
        paginator = Paginator(result, 15)
        try:
            result_page = paginator.page(page)
        except PageNotAnInteger:
            result_page = paginator.page(1)
        except EmptyPage as e:
            return {'retlist': [], 'curpageidx': page,
                    'hasnext': False, 'hasprevious': False}
        return {'retlist': list(result_page), 'curpageidx': page,
                'hasnext': result_page.has_next(), 'hasprevious': result_page.has_previous(),
                'total_page': paginator.num_pages}

    def get_evaluation_for_id(self, id):
        ret = list(self.filter(pk=id, is_show=1).values())
        return ret[0] if len(ret) > 0 else None


class ModelManagerAnswer(BasicManager):
    # 判断是否做过测评
    def get_answer_if_not_exist(self, user_id):
        res = self.filter(student_id=user_id).exists()
        return res

    def get_report(self, user_id):
        ret = self.filter(student_id=user_id).first()
        if not ret:
            return None
        if len(ret.top_four) == 1:
            ret.delete()
            res = self.handle_answer(json.loads(ret.score_json), user_id, ret.detail)
            if res['retcode'] == 1:
                return None
            ret = res['data']
        json_data = {
            'analysis': json.loads(ret.analysis),
            'proposal': json.loads(ret.proposal),
            'top_four': json.loads(ret.top_four),
            'final_score': json.loads(ret.final_score)
        }
        return json_data

    def handle_answer(self, answer, user_id, detail=None):
        try:
            if len(answer) < 25:
                return {'retcode': 1, 'msg': '答案数据异常'}
            is_complete = mm_Answer.get_answer_if_not_exist(user_id)
            if is_complete:
                return {'retcode': 1, 'msg': '重复提交答案'}
            if detail:
                fraction = answer
                detail = detail
            else:
                fraction = {}
                detail = {}
                with open("services/script_offline/subject.json", encoding='utf-8') as f:
                    line = f.readline()
                    subject_data = json.loads(line)
                    f.close()
                for key, value in answer.items():
                    v_sum = 0
                    for keys, v in value.items():
                        v_sum += int(v)
                        for ks in subject_data:
                            if ks.get('number') == str(keys):
                                detail[keys] = {'subject': ks['subjects'], 'sign': ks['sort'], 'key': key, 'score': v,
                                                'type': ks['type'], 'number': ks['number']}
                        fraction[key] = v_sum
            # 排序
            dict_sorted_rev = sorted(fraction.items(), key=lambda item: item[1], reverse=True)
            offset = 50
            new_score = {}
            for k, v in dict_sorted_rev:
                score = round(v*(1+(offset/100)), 2)
                new_score[k] = score
                if offset > 0:
                    offset -= 5
            top_four = dict(list(new_score.items())[0:10])
            group = collections.defaultdict(list)
            new_group = collections.defaultdict(list)
            group_name = {
                'a': {'type': '分析力', 'a': 'a', 'c': 'c'},
                'b': {'type': '创新力', 'b': 'b', 'd': 'd', 'e': 'e'},
                'c': {'type': '学习力', 'f': 'f', 'g': 'g'},
                'd': {'type': '共情力', 'h': 'h', 'i': 'i', 'j': 'j'},
                'e': {'type': '引领力', 'k': 'k', 'l': 'l', 'm': 'm'},
                'f': {'type': '交往力', 'n': 'n', 'o': 'o', 'p': 'p'},
                'g': {'type': '行动力', 'q': 'q', 'r': 'r', 's': 's'},
                'h': {'type': '目标力', 't': 't', 'u': 'u', 'v': 'v'},
                'i': {'type': '驱动力', 'w': 'w', 'x': 'x', 'y': 'y'},
            }
            for k, v in new_score.items():
                for ks, vs in group_name.items():
                    if vs.get(k) == str(k):
                        group[str(vs['type'])].append(v)
                        new_group[str(vs['type'])].append({'type': k, 'score': v})
            final_score = {}
            final_score_detail = dict()
            for k, v in group.items():
                number = len(v)
                group_sum = sum(v)
                average_score = round(group_sum/number, 2)
                final_score[k] = average_score  # 取平均分
                final_score_detail[k] = {'sum': group_sum, 'score': average_score}
            new_final_score = sorted(final_score.items(), key=lambda item: item[1], reverse=True)
            top_four_score = dict(list(new_final_score)[0:4])  # 从最终的分值取出前4--改数据并非最终数据
            index_name = {
                'a': '分析', 'c': '系统', 'b': '发散', 'd': '革新', 'e': '灵活',
                'f': '开放', 'g': '求知欲', 'h': '共情', 'i': '支持', 'j': '宽和',
                'k': '表达', 'l': '自信', 'm': '统领', 'n': '主动', 'o': '亲密',
                'p': '信任', 'q': '行动', 'r': '冒险', 's': '决断', 't': '条理',
                'u': '责任', 'v': '坚韧', 'w': '成就', 'x': '挑战', 'y': '信仰',
            }
            with open("services/script_offline/answer.json", encoding='utf-8') as f:
                line = f.readline()
                answer_data_t = json.loads(line)
                f.close()
            analysis = collections.defaultdict(list)  # 优势分析
            proposal = collections.defaultdict(list)  # 发展建议
            for k, v in top_four_score.items():
                analysis['title_name'].append([k, answer_data_t[k]['title']])
                for vs in new_group[k]:
                    name = index_name[vs['type']]
                    if vs['score'] >= 12.5:
                        analysis[k].append([answer_data_t[k]['detail'][name]['advantage']['a1']])
                        proposal['proposal'].append([k, answer_data_t[k]['detail'][name]['proposal']['b1']])
                        analysis['shortcoming'].append([k, answer_data_t[k]['detail'][name]['shortcoming']['c1']])
                    if vs['score'] < 12.5 and vs['type'] in top_four.keys():
                        analysis[k].append([answer_data_t[k]['detail'][name]['advantage']['a2']])
                        proposal['proposal'].append([k, answer_data_t[k]['detail'][name]['proposal']['b2']])
                        analysis['shortcoming'].append([k, answer_data_t[k]['detail'][name]['shortcoming']['c2']])
                    if vs['score'] < 12.5 and vs['type'] not in top_four.keys():
                        analysis['shortcoming'].append([k, answer_data_t[k]['detail'][name]['shortcoming']['c3']])
            excessive = collections.defaultdict(list)
            for v in proposal['proposal']:
                excessive[v[0]].append(v[1])
            assemble = collections.defaultdict(list)
            for v in excessive:
                for vs in excessive[v]:
                    for vvs in vs:
                        assemble[vvs['title']].append({'content': vvs['content'], 'name': v})
            opinion = collections.defaultdict(list)
            for v in assemble:
                opinion['proposal'].append([{'title': v, 'content': [i['content'] for i in assemble[v]],
                                             'name': assemble[v][0]['name']}])
            # 添加数据
            res = self.create(
                student_id=user_id,
                score_json=json.dumps(fraction),  # 用户提交原始答案
                detail=json.dumps(detail),
                final_score=json.dumps(final_score_detail),
                top_four=json.dumps(top_four_score),
                top_data=json.dumps(new_score),
                analysis=json.dumps(analysis),
                proposal=json.dumps(opinion)
            )
            # 获得3张免费礼品卡---实际这个没意义就是展示  放入缓存
            # key = "gift_card_user_count_%s" % str(user_id)
            # cache.set(key, 8, 3600*24*60)
            return {'retcode': 0, 'msg': 'OK', 'data': res}
        except Exception as e:
            app_logger.error(e)
            return {'retcode': 1, 'msg': '异常'}

    def update_student_answer_for_id(self, user_id, phone):
        resObj = self.get_or_default(student_id=user_id)
        if resObj:
            user = Student.objects.get_or_default(mobile=phone)
            if user:
                mobile_u = self.get_or_default(student_id=user.id)
                if not mobile_u:
                    resObj.student_id = user.id
                    resObj.save()

    def update_user(self, user_id, gender=None, age=0, occupation=None, provinceid=None, cityid=None, districtid=None,
                    provincename=None, cityname=None, districtname=None, entry_time=None):
        Student.objects.filter(id=user_id).update(
            gender=gender,
            age=age,
            occupation=occupation,
            provinceid=provinceid,
            cityid=cityid,
            districtid=districtid,
            provincename=provincename,
            cityname=cityname,
            districtname=districtname,
            entry_time=entry_time
        )

    def export_user_report(self, start_date=None,  end_date=None, evachid=None):
        try:
            query = Q(created_at__range=[start_date, end_date])
            query &= ~Q(top_four=0)
            if evachid:
                query = query & Q(student__eva_channel=evachid)
            result = self.filter(query).values('score_json', 'student__nick_name', 'student__mobile', 'final_score',
                                                  'detail', 'top_four', 'top_data', 'student__age', 'student__gender',
                                                  'student__provincename', 'student__cityname', 'student__districtname',
                                                  'student__channel', 'student__marriage', 'student__education',
                                                  'student__occupation', 'student_id', 'created_at',
                                               'student__eva_channel_name'
                                               ).order_by("-created_at")
            name = {1: '分析力', 2: '创新力', 3: '学习力', 4: '共情力', 5: '引领力', 6: '交往力', 7: '行动力', 8: '目标力',
                    9: '驱动力'}
            li_name = {'思维力': ['分析力', '创新力', '学习力'], '关系力': ['共情力', '引领力', '交往力'], '执行力':
                       ['行动力', '目标力', '驱动力']}
            ws = xlwt.Workbook(encoding="UTF-8")
            w = ws.add_sheet(u'数据')
            w.write(0, 0, u'用户编号')
            w.write(0, 1, u'分析力')
            w.write(0, 2, u'创新力')
            w.write(0, 3, u'学习力')
            w.write(0, 4, u'共情力')
            w.write(0, 5, u'引领力')
            w.write(0, 6, u'交往力')
            w.write(0, 7, u'行动力')
            w.write(0, 8, u'目标力')
            w.write(0, 9, u'驱动力')
            w.write(0, 10, u'手机号')
            w.write(0, 11, u'年龄')
            w.write(0, 12, u'性别')
            w.write(0, 13, u'地区')
            w.write(0, 14, u'行业')
            w.write(0, 15, u'姓名')
            w.write(0, 16, u'提交时间')
            w.write(0, 17, u'渠道')
            w.write(0, 18, u'推荐')
            w.write(0, 19, u'渠道名称')
            excel_row = 1
            for obj in result:
                w.write(excel_row, 0, obj['student_id'])
                final = json.loads(obj['final_score'])
                top_data = {}
                recommend_arr = {}
                for k in name:
                    top_data[k] = final[name[k]]['score']
                dict_sorted_rev = sorted(top_data.items(), key=lambda item: item[1], reverse=True)
                top_four = json.loads(obj['top_four'])
                for k in name:
                    i = 1
                    for ks, vs in dict_sorted_rev:
                        if k == ks:
                            w.write(excel_row, k, str(vs)+'/'+str(i))
                        i += 1
                for k in li_name:
                    sum = 0
                    for ks in top_four:
                        if ks in li_name[k]:
                            sum += top_four[ks]
                            recommend_arr[k] = sum
                dict_sorted_re = sorted(recommend_arr.items(), key=lambda item: item[1], reverse=True)
                w.write(excel_row, 10, obj['student__mobile'])
                w.write(excel_row, 11, obj['student__age'])
                w.write(excel_row, 12, str(obj['student__gender']))
                w.write(excel_row, 13, str(obj['student__provincename'])+str(obj['student__cityname'])+str(obj['student__districtname']))
                w.write(excel_row, 14, obj['student__occupation'])
                w.write(excel_row, 15, str(obj['student__nick_name']))
                w.write(excel_row, 16, obj['created_at'].strftime('%Y-%m-%d %H:%M:%S'))
                w.write(excel_row, 17, obj['student__channel'])
                w.write(excel_row, 18, dict_sorted_re[0][0])
                w.write(excel_row, 19, obj['student__eva_channel_name'])
                excel_row += 1
            sio = BytesIO()
            ws.save(sio)
            sio.seek(0)
            response = HttpResponse(sio.getvalue(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename=stu_info.xls'
            response.write(sio.getvalue())
            return response
        except Exception as e:
            app_logger.error(e)
            return {'retcode': 1, 'msg': '异常'}

    def get_poster_copywriting(self, user_id):
        res = self.filter(student_id=user_id).values('top_four')
        if not res:
            return False
        if res[0]['top_four'] == '0':
            report = self.get_report(user_id)
            top = report['top_four']
        else:
            top = json.loads(res[0]['top_four'])
        with open("services/script_offline/poster.json", encoding='utf-8') as f:
            line = f.readline()
            poster_data = json.loads(line)
            f.close()
        copywriting = collections.defaultdict(list)
        for k, v in top.items():
            copywriting['a'].append([k, poster_data['a'][k]])
            copywriting['b'].append([k, poster_data['b'][k]])
            copywriting['c'].append([k, poster_data['c'][k]])
        return copywriting

    def add_poster(self, user_id, url):
        res = self.get_or_default(student_id=user_id)
        if res:
            res.poster = url
            res.save()

    def get_advantage(self, user_id):
        user_answer = mm_Answer.filter(student_id=user_id).first()
        # top_data = {}
        top_arr = []
        # dict_sorted_re = []
        if user_answer:
            if len(user_answer.top_four) == 1:
                user_answer.delete()
                res = self.handle_answer(json.loads(user_answer.score_json), user_id, user_answer.detail)
                if res['retcode'] == 1:
                    return None
                user_answer = res['data']
            # name = {1: '分析力', 2: '创新力', 3: '学习力', 4: '共情力', 5: '引领力', 6: '交往力', 7: '行动力', 8: '目标力', 9: '驱动力'}
            # li_name = {'思维力': ['分析力', '创新力', '学习力'], '关系力': ['共情力', '引领力', '交往力'], '执行力':
            #            ['行动力', '目标力', '驱动力']}
            final = json.loads(user_answer.final_score)
            i = 1
            for k, v in final.items():
                top_arr.append({'score': v['score'], 'name': k})
            top_arr = sorted(top_arr, key=lambda item: item['score'], reverse=True)
            for v in top_arr:
                v['sort'] = i
                i += 1
            # recommend_arr = {}
            # for k in name:
            #     top_data[k] = final[name[k]]['score']
            # dict_sorted_rev = sorted(top_data.items(), key=lambda item: item[1], reverse=True)
            # for k, v in enumerate(dict_sorted_rev):
            #     top_arr.append({'sort': k+1, 'score': v[1], 'name': name[v[0]]})
        return {'retcode': 0, 'msg': "OK", 'data': top_arr}

    def get_opinion(self, user_id):
        li_name = {'思维': ['分析力', '创新力', '学习力'], '关系': ['共情力', '引领力', '交往力'], '执行': ['行动力', '目标力',
                                                                                    '驱动力']}
        res = self.filter(student_id=user_id).first()
        if res:
            top_four = json.loads(res.top_four)
            recommend_arr = {}
            category = collections.defaultdict(list)
            for k in li_name:
                sum = 0
                for ks in top_four:
                    if ks in li_name[k]:
                        category[k].append({'name': ks})
                        sum += top_four[ks]
                        recommend_arr[k] = sum
            dict_sorted_re = sorted(recommend_arr.items(), key=lambda item: item[1], reverse=True)
            with open("services/script_offline/proposal.json", encoding='utf-8') as f:
                line = f.readline()
                proposal_data = json.loads(line)
                f.close()
            recommend = {}
            for v in dict_sorted_re:
                if len(category[v[0]]) >= 2:
                    recommend[v[0]] = {'name': v[0], 'content': proposal_data['action'][v[0]]}

            return {'recommend': recommend, 'category': category, 'top_four': top_four, 'development':
                    proposal_data['development'], 'introduction': {'name': dict_sorted_re[0][0], 'content': proposal_data['development'][dict_sorted_re[0][0]]['introduction']}}


class ModelManagerEvaluationChannel(BasicManager):

    def creates(self, name, nums, wy=0, enable=0, is_new=0):
        try:
            code = str(uuid.uuid4())
            url = DOMAIN_URL + EVALUATION_0_Link + code
            if is_new == 0:
                new_link = '/h5/#/h5/h5-Appraisal-Switch?isPay=0&channel=1&urlId=1&evach='
                url = DOMAIN_URL + new_link + code
            if wy:
                url = url + '&wy=1'
            channel = self.create(name=name,
                                  nums=nums,
                                  evach=code,
                                  url=url,
                                  enable=enable,
                                  is_new=is_new)
            url = url + '&id='+str(channel.id)
            channel.url = url
            channel.save()
            return JsonResponse({'retcode': 0})
        except IntegrityError as e:
            return JsonResponse({'retcode': 1, 'msg': "该渠道名已被使用！"})

    # 获取列表
    def get_list(self, page, detail=1, query=None):
        if detail:
            result = self.values().order_by("-created_at")
        else:
            result = self.values("id", "name", "enable", "is_new").order_by("-created_at")
            return {'retlist': list(result)}
        if query:
            result = result.filter(name__icontains=query)
        if not page:
            return {'retcode': 0, 'retlist': list(result)}
        paginator = Paginator(result, 15)
        try:
            result_page = paginator.page(page)
        except PageNotAnInteger:
            result_page = paginator.page(1)
        except EmptyPage as e:
            return {'retlist': [], 'curpageidx': page,
                    'hasnext': False, 'hasprevious': False}
        return {'retlist': list(result_page), 'curpageidx': page,
                'hasnext': result_page.has_next(), 'hasprevious': result_page.has_previous(),
                'total_page': paginator.num_pages}

    def get_evaluation_for_id(self, id):
        ret = list(self.filter(pk=id, is_show=1).values())
        return ret[0] if len(ret) > 0 else None


class Evaluation(models.Model):
    name = models.CharField("名称", max_length=50)
    is_show = models.PositiveSmallIntegerField("是否显示", default=0)
    charge = models.IntegerField('价格', default=0)  # 单位：分
    created_at = models.DateTimeField("添加时间", auto_now_add=True)
    updated_at = models.DateTimeField("修改时间", auto_now=True)

    objects = ModelManagerEvaluation()

    class Meta:
        verbose_name = ''
        verbose_name_plural = verbose_name
        db_table = "momself_evaluation"

    def __str__(self):
        return self.name


class Answer(models.Model):
    student = models.ForeignKey(Student, related_name='answer_student')
    # {"c":21,"i":21,"x":18,"o":18,"j":17,"t":17} 分值
    score_json = models.TextField("分值")
    # [{"subject":"题目1","sign":1,"key":"w","score":2,"type":"\u6210\u5c31","number":"w4"},
    # {"subject":"题目2","sign":2,"key":"w","score":4,"type":"\u6210\u5c31","number":"w1"}]
    detail = models.TextField("数据题目答案详情")
    # {"c":"42.00","i":"39.90","x":"32.40","o":"30.60","j":"27.20","t":"25.50"}  最后分值
    final_score = models.TextField("最后分值")
    # [{"type":"\u5206\u6790\u529b","rank":1,"score":"41.75"},{"type":"\u5171\u60c5\u529b","rank":2,"score":"35.27"},
    # {"type":"\u884c\u52a8\u529b","rank":3,"score":"25.40"},{"type":"\u5b66\u4e60\u529b","rank":4,"score":"23.70"}]
    top_four = models.CharField("排名前四", max_length=150)
    # {"\u601d\u7ef4":[{"ranking":1,"name":"\u5b66\u4e60\u529b"},{"ranking":3,"name":"\u521b\u65b0\u529b"}],
    # "\u5173\u7cfb":[{"ranking":2,"name":"\u5171\u60c5\u529b"},{"ranking":4,"name":"\u5f15\u9886\u529b"}],"\u6267\u884c":[]}
    top_data = models.TextField("靠前数据")
    analysis = models.TextField("优势分析")
    proposal = models.TextField("发展建议")
    poster = models.TextField("H5海报", default="")
    created_at = models.DateTimeField("添加时间", auto_now_add=True)
    updated_at = models.DateTimeField("修改时间", auto_now=True)

    objects = ModelManagerAnswer()

    class Meta:
        verbose_name = ''
        verbose_name_plural = verbose_name
        db_table = "momself_answer"


class EvaluationChannel(models.Model):
    url = models.CharField("链接", max_length=200)
    name = models.CharField("渠道名称", max_length=50, unique=True)
    nums = models.IntegerField('限制名额', default=0)
    used = models.IntegerField('已用名额数', default=0)
    evach = models.CharField("唯一标识码", max_length=50, unique=True)  # 分享时使用
    enable = models.PositiveSmallIntegerField("功能是否开启", default=0)  # 默认0是开启  1是关闭
    is_new = models.PositiveSmallIntegerField("是否新链接", default=0)  # 默认0是  1不是
    created_at = models.DateTimeField("添加时间", auto_now_add=True)
    updated_at = models.DateTimeField("修改时间", auto_now=True)

    objects = ModelManagerEvaluationChannel()

    class Meta:
        verbose_name = ''
        db_table = "momself_evaluation_channel"

    def __str__(self):
        return self.name


mm_Evaluation = Evaluation.objects
mm_Answer = Answer.objects
mm_EvaluationChannel = EvaluationChannel.objects
